#!/bin/bash
#
# Pulley routines and globals for managing agents
#
# Author:   Dr. Mike Murphy (mmurphy2@coastal.edu)
# Revision: 19 November 2013
#
#   Copyright 2013 Coastal Carolina University
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.


declare -a -g P_AGENTS


## validate_agent <agent name>
##
## Checks to see if <agent name> is a valid name of an agent that has been
## enabled with the enable_agent function. Returns 0 iff the name is valid.
##
function validate_agent() {
	is_element "$1" "${P_AGENTS[@]}"
	return $?
}


## agent_summary <agent name>
##
## Echoes the summary information for the agent specified by <agent name>.
## Returns 0 upon success, 2 if the <agent name> is invalid. Also writes an
## error message if the <agent name> is invalid.
##
function agent_summary() {
	local status=0
	if validate_agent "$1"; then
		p_agent_"$1"_summary
		status=$?
	else
		echo "Agent unknown or not enabled: $1"
		status=2
	fi
	return ${status}
}


## agent_help <agent name>
##
## Echoes the defined help message for the agent named <agent name>. If the
## <agent name> is invalid, or if the agent is not enabled, writes an error
## message and returns 2. Returns 0 on success.
##
function agent_help() {
	local status=0
	if validate_agent "$1"; then
		p_agent_"$1"_help
		status=$?
	else
		echo "Agent unknown or not enabled: $1"
		status=2
	fi
	return ${status}
}


## run_agent <agent name>
##
## Runs the agent specified by <agent name> in normal operating mode. If the
## <agent name> is invalid or refers to an agent that is not enabled, writes
## an error message and returns 2. Otherwise, returns the exit status of the
## executed agent.
##
function run_agent() {
	local status=0
	
	if validate_agent "$1"; then
		"p_agent_$1_run"
		status=$?
	else
		echo "Agent unknown or not enabled: $1"
		status=2
	fi
	
	return ${status}
}


## check_agent <agent name>
##
## Instructs the agent specified by <agent name> to run update checking
## routines. Returns 2 and issues a message to standard error if the
## <agent name> is invalid or refers to an agent that has not been enabled.
## Otherwise, returns the exit status of the agent's check routine, which
## should be 0 to indicate no updates are available, 100 to indicate that
## updates are available, or another non-zero value on error.
##
function check_agent() {
	local status=0
	
	if validate_agent "$1"; then
		if is_function "p_agent_$1_check"; then
			"p_agent_$1_check"
			status=$?
		fi
	else
		echo "Agent unknown or not enabled: $1"
		status=2
	fi
	
	return ${status}
}


## run_agents
##
## Runs all enabled agents in normal operation mode. Returns 0 if all agents
## return 0; otherwise returns the *first* non-zero exit status encountered.
## Receiving a non-zero exit status does NOT terminate execution: all
## remaining agents will still execute. However, the non-zero return code
## of this function will be the exit status of the first agent that
## indicated an error.
##
function run_agents() {
	local status=0
	
	for agent in "${P_AGENTS[@]}"; do
		run_agent "${agent}"
		status=$(merge_status ${status} $?)
	done
	
	return ${status}
}


## check_agents
##
## Runs the update checking routines in enabled agents. Returns 0 if all
## agents indicate that no updates are available. Otherwise, returns the
## *first* non-zero exit status returned by any agent. This exit status
## should be 100 if updates are available, or another non-zero value if
## errors were encountered.
##
function check_agents() {
	local status=0
	
	for agent in "${P_AGENTS[@]}"; do
		check_agent "${agent}"
		status=$(merge_status ${status} $?)
		
		if ((status != 0)); then
			break
		fi
	done
	
	return ${status}
}


## load_agent <agent name or path> [<agent name or path> ...]
##
## Loads the agent specified by <agent name or path>. If an agent file with
## the name <agent name>.agent is located in the agents subdirectory of the
## Pulley library directory, then that file will be sourced. Otherwise, this
## function will attempt to source the file given as an argument. Returns 0
## on success, non-zero otherwise.
##
function load_agent() {
	local status=0
	
	for arg in "$@"; do
		if [[ -f "${P_LIBDIR}/agents/$1.agent" ]]; then
			. "${P_LIBDIR}/agents/$1.agent"
			status=$(merge_status ${status} $?)
		else
			if [[ -f "$1" ]]; then
				. "$1"
				status=$(merge_status ${status} $?)
			else
				echo "ERROR: Agent not found for loading: $1"
				status=2
			fi
		fi
	done
	
	return ${status}
}


## enable_agent <agent name>
##
## Enables an agent named <agent name>. If the agent's execution function
## is not defined, also tries to load the agent with load_agent.
##
function enable_agent() {
	local status=0
	
	if is_function p_agent_$1_run; then
		P_AGENTS+=("$1")
	else
		load_agent "$1"
		status=$?
		
		if ((status == 0)); then
			P_AGENTS+=("$1")
		fi
	fi
	
	return ${status}
}
